#!/bin/bash

include "objectv2.sh"
include "regex.sh"
include "test.sh"

objectv2::define_struct Python "
    --cargs=cmdfifo,resfifo
    --string=cmdfifo
    --string=resfifo
    --string=pid
"

function Python::MakeEmpty()
{
    local obj="$1"
    local fifo1="$(mktemp --dry-run "/tmp/python.cmd.XXXXXXXX")"
    if ! mkfifo -m 777 "$fifo1"; then
        loge "Python default mkfifo 1 failed"
        return 1
    fi

    local fifo2="$(mktemp --dry-run "/tmp/python.res.XXXXXXXX")"
    if ! mkfifo -m 777 "$fifo2"; then
        loge "Python default mkfifo 2 failed"
        rm "$fifo1"
        return 1
    fi

    Python $obj{"$fifo1", "$fifo2"}
}

function Python::Python()
{
    local obj="$1"
    Python::pid "$obj" "$BASHPID"
}

function Python::~Python()
{
    local obj="$1"
    local cmdfifo="$(Python::cmdfifo "$obj")"
    local resfifo="$(Python::resfifo "$obj")"
    Python::ExecNoResponse "$obj" "exit(0)"
    rm -f "$cmdfifo" "$resfifo"
}

function Python::StartServer()
{
    local obj="$1"
    local cmdfifo="$(Python::cmdfifo "$obj")"
    local resfifo="$(Python::resfifo "$obj")"
    local pid="$(Python::pid "$obj")"
    if ! [[ "$pid" =~ (^${regex_dec_integer}$) ]]; then
        loge "Python default.pid不是数字"
        return 1
    fi

    local server_code='
        import os as __os__
        import select as __select__

        __poller__ = __select__.poll()
        __poller__.register(__os__.open("'$cmdfifo'", __os__.O_RDONLY | __os__.O_NONBLOCK), __select__.POLLIN)

        def response(result):
            __responser__ = __os__.open("'$resfifo'", __os__.O_WRONLY)
            __os__.write(__responser__, (str(result) + "\n").encode(encoding="utf-8"))
            __os__.close(__responser__)

        while __os__.path.exists("/proc/'$pid'"):
            for __fd__, __flag__ in __poller__.poll(5000):
                if not __flag__ & __select__.POLLIN:
                    continue

                __number__ = ""
                while True:
                    __ch__ = __os__.read(__fd__, 1).decode(encoding="utf-8")
                    if __ch__ == "\n":
                        break
                    __number__ += __ch__

                try:
                    exec(__os__.read(__fd__, int(__number__)).decode(encoding="utf-8"))
                except Exception as __e__:
                    response("error:" + str(__e__))

        __os__.remove("'$cmdfifo'")
        __os__.remove("'$resfifo'")
    '
    python <<< "$(print_source 8 server_code)" &
}

if Python::MakeEmpty default; then
    Python::StartServer default
fi

function Python::Exec()
{
    local obj="$1"
    local cmdfifo="$(Python::cmdfifo "$obj")"
    local resfifo="$(Python::resfifo "$obj")"
    local content="$2"
    if [ "$content" == "" ]; then
        loge "没有代码可以运行"
        return 1
    fi

    echo -en "${#content}\n${content}" > "$cmdfifo"
    cat "$resfifo"
}

function Python::ExecNoResponse()
{
    local obj="$1"
    local cmdfifo="$(Python::cmdfifo "$obj")"
    local content="$2"
    if [ "$content" == "" ]; then
        loge "没有代码可以运行"
        return 1
    fi

    echo -en "${#content}\n${content}" > "$cmdfifo"
}

function Python::Exec::test1()
{
    local test_code1="
        response(1)
    "

    local test_code2="
        import yyyymmmmaaaallll
    "

    test::run_cmd Python::Exec default "$(print_source 8 test_code1)"
    test::should_be "1"

    test::run_cmd Python::Exec default "$(print_source 8 test_code2)"
    test::should_be "error:No module named 'yyyymmmmaaaallll'"

    test::should_return_false Python::Exec default ""
}
test::register_test Python::Exec::test1
